#include "StdAfx.h"
#include "appsettings.h"
#include "tableviewbase.h"

TableHeaderViewBase::TableHeaderViewBase( Qt::Orientation orientation, QWidget * parent )
:   QHeaderView( orientation, parent )
{
    setSortIndicatorShown( true );
}

TableHeaderViewBase::~TableHeaderViewBase()
{
}

void TableHeaderViewBase::contextMenuEvent( QContextMenuEvent * event )
{
    emit contextMenu( event->globalPos() );
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////

TableItemDelegateBase::TableItemDelegateBase( const TableHeaderViewBase & tableHeaderViewBase, QObject * parent )
:   QItemDelegate( parent ),
    m_tableHeaderViewBase( tableHeaderViewBase )
{
}

TableItemDelegateBase::~TableItemDelegateBase()
{
}

void TableItemDelegateBase::drawFocus( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect ) const
{
    if (isFlag( option.state, QStyle::State_Selected ))
    {
        QStyleOptionFocusRect o;
        o.QStyleOption::operator=(option);
        o.state |= QStyle::State_KeyboardFocusChange;
        o.state |= QStyle::State_Item;
        QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
                              ? QPalette::Normal : QPalette::Disabled;
        o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
                                             ? QPalette::Highlight : QPalette::Window);
        QRect r( o.rect );
        if (r.x() == 0)
        {
            o.rect.setRect( 0, r.y(), 1, r.height() );
            QApplication::style()->drawPrimitive( QStyle::PE_FrameFocusRect, & o, painter, NULL );
        }

        o.rect.setRect( r.x(), r.y(), r.width(), 1 );
        QApplication::style()->drawPrimitive( QStyle::PE_FrameFocusRect, & o, painter, NULL );

        o.rect.setRect( r.x(), r.y() + r.height() - 1, r.width(), 1 );
        QApplication::style()->drawPrimitive( QStyle::PE_FrameFocusRect, & o, painter, NULL );

        int headerLength = m_tableHeaderViewBase.length();
        if (r.x() + r.width() == headerLength - 1)
        {
            o.rect.setRect( headerLength - 2, r.y(), 1, r.height() );
            QApplication::style()->drawPrimitive( QStyle::PE_FrameFocusRect, & o, painter, NULL );
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////

TableViewBase::TableViewBase(  QWidget * parent )
:   QTableView( parent ),
    m_horizontalHeaderView( Qt::Horizontal, this )
{
    _init();
}

TableViewBase::~TableViewBase()
{
}

void TableViewBase::init()
{
    _init();
}

void TableViewBase::_init()
{
    setSelectionMode( QAbstractItemView::SingleSelection );
    setSelectionBehavior( QAbstractItemView::SelectRows );
    setEditTriggers( EditTriggers() );
    setSortingEnabled( true );
    setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel );
    
    setVerticalHeaderView();
    setHorizontalHeaderView();
}

void TableViewBase::setVerticalHeaderView()
{
    QHeaderView * verticalHdr = verticalHeader();
    verticalHdr->hide();
    verticalHdr->setDefaultSectionSize( 20/*AppSettings::tableRowHeight()*/ );
}

void TableViewBase::setHorizontalHeaderView()
{
    setItemDelegate( new TableItemDelegateBase( m_horizontalHeaderView, this ) );
    m_horizontalHeaderView.setMovable( true );
    m_horizontalHeaderView.setHighlightSections( false );
    m_horizontalHeaderView.setClickable( true );
    setHorizontalHeader( & m_horizontalHeaderView );
    connect( & m_horizontalHeaderView, SIGNAL( contextMenu( const QPoint & ) ), this, SLOT( onHeaderContextMenu( const QPoint & ) ) );
}

void TableViewBase::saveHeaderViewState( const QString & headerViewName ) const
{
    AppSettings::saveHeaderViewState( m_horizontalHeaderView, headerViewName );
}

void TableViewBase::restoreHeaderViewState( const QString & headerViewName )
{
    AppSettings::restoreHeaderViewState( m_horizontalHeaderView, headerViewName );
}

void TableViewBase::onHeaderContextMenu( const QPoint & pos )
{
    QAbstractItemModel * itemModel = model();
    if (itemModel == NULL)
        return;
 
    QMenu menu( this );
    QAction * action;
    int visibleSectionCount = 0;
    for (int i = 0; i < m_horizontalHeaderView.count(); i++)
    {
        action = new QAction( itemModel->headerData( i, Qt::Horizontal ).toString(), & menu );
        action->setCheckable( true );
        bool isSectionVisible = ! m_horizontalHeaderView.isSectionHidden( i );
        action->setChecked( isSectionVisible );
        if (isSectionVisible)
        {
            visibleSectionCount ++; 
        }

        action->setData( i );
        menu.addAction( action );
    }

    action = menu.exec( pos );
    if (action == NULL)
        return;

    QVariant variant = action->data();
    if (variant.isValid())
    {
       bool hideSection = ! action->isChecked();
       if (hideSection)
       {
           if (visibleSectionCount > 1)
           {
                m_horizontalHeaderView.setSectionHidden( variant.toInt(), true );
           }
       }
       else
       {
           m_horizontalHeaderView.setSectionHidden( variant.toInt(), false );
       }
    }
}


void TableViewBase::contextMenuEvent( QContextMenuEvent * event )
{
    QItemSelectionModel * selModel = selectionModel();
    if (selModel == NULL)
        return;

    // you can use only user data in the first column
    QModelIndexList modelIndexList = selModel->selectedIndexes();
    QModelIndexList selModelIndexList;
    QModelIndexList::const_iterator it;
    FOREACH (it, modelIndexList)
    {
        if (it->column() == 0)
        {
            selModelIndexList.push_back( * it );
        }
    }

    int size = selModelIndexList.size();
    switch (size)
    {
    case 0:
        emit contextMenu( event->globalPos(), QModelIndex() );
        break;

    case 1:
        emit contextMenu( event->globalPos(), * selModelIndexList.begin() );
        break;

    default:
        emit contextMenuMultiSelection( event->globalPos(), selModelIndexList );
        break;
    }
}

TableHeaderViewBase & TableViewBase::horizontalHeaderView()
{
    return m_horizontalHeaderView;
}

void TableViewBase::selectRowByData( QVariant & data )
{
    if (! data.isValid())
        return;

    QAbstractItemModel * abstractModel = model();
    if (abstractModel == NULL)
        return;

    int rowCount = abstractModel->rowCount();
    for (int i = 0; i < rowCount; i++)
    {
        if (data == abstractModel->data( abstractModel->index( i, 0 ), Qt::UserRole + 1 ))
        {
            selectRow( i );
            return;
        }
    }
}
